bitkeeper revision 1.1159.84.1 (4152ffb0bojKEycaCbGsqN5sCuR7RQ)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Thu, 23 Sep 2004 16:54:08 +0000 (16:54 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Thu, 23 Sep 2004 16:54:08 +0000 (16:54 +0000)
Optimize network handling of small packets.

linux-2.6.8.1-xen-sparse/drivers/xen/netback/netback.c

index ca12459175836d75141dc812d12eeb0d99bbda53..d1524b1f6e5aee233e9ad81ec4a52de3ac1cef88 100644 (file)
@@ -13,6 +13,7 @@
 #include "common.h"
 
 static void netif_page_release(struct page *page);
+static void netif_skb_release(struct sk_buff *skb);
 static void make_tx_response(netif_t *netif, 
                              u16      id,
                              s8       st);
@@ -40,7 +41,8 @@ static unsigned char rx_notify[NR_EVENT_CHANNELS];
 static unsigned long mmap_vstart;
 #define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE))
 
-#define PKT_PROT_LEN (ETH_HLEN + 20)
+#define PKT_MIN_LEN (ETH_HLEN + 20)
+#define PKT_PROT_LEN 64
 
 static struct {
     netif_tx_request_t req;
@@ -385,6 +387,7 @@ static void net_tx_action(unsigned long unused)
     NETIF_RING_IDX i;
     multicall_entry_t *mcl;
     PEND_RING_IDX dc, dp;
+    unsigned int data_len;
 
     if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
         goto skip_dealloc;
@@ -497,7 +500,7 @@ static void net_tx_action(unsigned long unused)
 
         netif_schedule_work(netif);
 
-        if ( unlikely(txreq.size <= PKT_PROT_LEN) || 
+        if ( unlikely(txreq.size <= PKT_MIN_LEN) || 
              unlikely(txreq.size > ETH_FRAME_LEN) )
         {
             DPRINTK("Bad packet size: %d\n", txreq.size);
@@ -519,7 +522,9 @@ static void net_tx_action(unsigned long unused)
 
         pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
 
-        if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) )
+        data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size;
+
+        if ( unlikely((skb = alloc_skb(data_len+16, GFP_ATOMIC)) == NULL) )
         {
             DPRINTK("Can't allocate a skb in start_xmit.\n");
             make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
@@ -578,19 +583,28 @@ static void net_tx_action(unsigned long unused)
         phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
             FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
 
-        __skb_put(skb, PKT_PROT_LEN);
+        data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size;
+
+        __skb_put(skb, data_len);
         memcpy(skb->data, 
                (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
-               PKT_PROT_LEN);
-
-        /* Append the packet payload as a fragment. */
-        skb_shinfo(skb)->frags[0].page        = 
-            virt_to_page(MMAP_VADDR(pending_idx));
-        skb_shinfo(skb)->frags[0].size        = txreq.size - PKT_PROT_LEN;
-        skb_shinfo(skb)->frags[0].page_offset = 
-            (txreq.addr + PKT_PROT_LEN) & ~PAGE_MASK;
-        skb_shinfo(skb)->nr_frags = 1;
-        skb->data_len  = txreq.size - PKT_PROT_LEN;
+               data_len);
+
+        if (data_len < txreq.size) {
+            /* Append the packet payload as a fragment. */
+            skb_shinfo(skb)->frags[0].page        = 
+                virt_to_page(MMAP_VADDR(pending_idx));
+            skb_shinfo(skb)->frags[0].size        = txreq.size - data_len;
+            skb_shinfo(skb)->frags[0].page_offset = 
+                (txreq.addr + data_len) & ~PAGE_MASK;
+            skb_shinfo(skb)->nr_frags = 1;
+        } else {
+            skb_shinfo(skb)->frags[0].page        = 
+                virt_to_page(MMAP_VADDR(pending_idx));
+            skb->destructor = netif_skb_release;
+        }
+
+        skb->data_len  = txreq.size - data_len;
         skb->len      += skb->data_len;
 
         skb->dev      = netif->dev;
@@ -606,13 +620,9 @@ static void net_tx_action(unsigned long unused)
     }
 }
 
-static void netif_page_release(struct page *page)
+static void netif_idx_release(u16 pending_idx)
 {
     unsigned long flags;
-    u16 pending_idx = page - virt_to_page(mmap_vstart);
-
-    /* Ready for next use. */
-    set_page_count(page, 1);
 
     spin_lock_irqsave(&dealloc_lock, flags);
     dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
@@ -621,6 +631,24 @@ static void netif_page_release(struct page *page)
     tasklet_schedule(&net_tx_tasklet);
 }
 
+static void netif_page_release(struct page *page)
+{
+    u16 pending_idx = page - virt_to_page(mmap_vstart);
+
+    /* Ready for next use. */
+    set_page_count(page, 1);
+
+    netif_idx_release(pending_idx);
+}
+
+static void netif_skb_release(struct sk_buff *skb)
+{
+    struct page *page = skb_shinfo(skb)->frags[0].page;
+    u16 pending_idx = page - virt_to_page(mmap_vstart);
+
+    netif_idx_release(pending_idx);
+}
+
 #if 0
 long flush_bufs_for_netif(netif_t *netif)
 {